/*
 * @Author: your name
 * @Date: 2020-08-19 20:22:46
 * @LastEditTime: 2020-08-19 21:06:39
 * @LastEditors: Please set LastEditors
 * @Description: In User Settings Edit

 * @FilePath: \demo\day02\demo08\main.go
 */
package main

import "fmt"

// 建造者模式

// 一层层的建造

// 第一层
type Builder interface {
	Build()
}

// 第二层 返回第一层的接口
type Director struct {
	builder Builder
}

// 第二层拥有初始化的方法
func NewBuilder(b Builder) Director {
	return Director{builder: b}
}

// 第二层可以调用第一层的方法
func (d *Director) Construct() {
	d.builder.Build()
}

// 第三层 <承上启下 ；也是做动作的一层，同时也是初始化一层>
type ConcreteBuilder struct {
	built bool
}

// 第三层初始化方法
func NewConcreteBuilder() ConcreteBuilder {
	return ConcreteBuilder{}
}

// 第三层实例方法 // do-something 动作，证明自己是第一层的子类，因为实现第一层接口的方法
func (b *ConcreteBuilder) Build() {
	b.built = true
}

// 第三层的方法实例化第四层,同时把第三层的值通过第二层的<子类实例化的>调用第三层的Build方法
// 传值给built，然后再次初始化第四层的product
func (b *ConcreteBuilder) GetResult() Product {
	return Product{Built: b.built}
}

// 第四层
type Product struct {
	Built bool
}

func main() {
	// 初始化第三层
	concreteBuilder := NewConcreteBuilder()
	// 获得第三层的 初始化
	// 然后动态初始化第二层
	// 由于第三层返回 的结果是第一层的子类中都有Build()方法，所以可以直接注入
	construct := NewBuilder(&concreteBuilder)
	// 第三层调用自己的方法
	// 内部则是，用子类的实例化调用子类的方法
	construct.Construct()
	// 初始化第四层
	result := concreteBuilder.GetResult()
	// 同时打印结果
	fmt.Println(result.Built)
}
